#include <stdio.h>
#include <vector>
#include <pthread.h>
#include <queue>

#include "../log.h"

using namespace LOG;

#define P_NUM 2
#define C_NUM 2
#define MAX_TASK 6

typedef void *(*Task)(void *);

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 互斥锁

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;   // 条件变量





class p_thread // 生产者线程
{
private:
    bool CreatProducerThread()
    {
        for (size_t i = 0; i < _num; i++)
        {
            // 创建线程
            pthread_t id;
            int n = pthread_create(&id, nullptr, _task, nullptr);
            if (n != 0) // 创建失败
            {
                lg(FATAL, "producer thread create fail...");
                return false;
            }
            _ProducerThread_v.push_back(id);
            lg(DEBUG, "a producer thread create...all: %d", _ProducerThread_v.size());
        }
        return true;
    }

    void WaitThread()
    {
        // 等待线程终止后销毁
        for (auto e : _ProducerThread_v)
        {
            void *ret;
            pthread_join(e, &ret);
            int retu = (size_t)ret;
            lg(INFO, "p_thread's id is: %zu,return value is: %zu", e, retu);
        }
    }
public:
    p_thread(Task task, size_t num):
    _num(num),                                          
    _task(task)
    {
        // 创建生产者线程 && 执行方法
        CreatProducerThread();
    }

    ~p_thread()
    {
        //_p_cond = PTHREAD_COND_INITIALIZER;
        WaitThread();
    }

private:
    size_t _num;                              // 生产者线程数量
    std::vector<pthread_t> _ProducerThread_v; // 生产者线程的id
    Task _task;                               // 生产者线程执行的方法
};

//-----------------------------------------------------------------------------------------

class taskqueue// 任务队列
{
public:
    taskqueue(size_t num = MAX_TASK):
    _num(num)
    {
    }
    ~taskqueue()
    {
    }

    void AddTask(Task task)//添加任务
    {
        pthread_mutex_lock(&mutex);             // 加锁
        while(_task.size() == _num)             // 任务队列满了
        {
            pthread_cond_signal(&cond);         // 唤醒一个消费者
            pthread_cond_wait(&cond, &mutex);   // 自己再等消费者唤醒
        }
        _task.emplace(task);                    // 添加任务到队列
        pthread_mutex_unlock(&mutex);           // 解锁      
    }

    void GetAndExcelTask()//获取任务 && 执行任务
    {
        pthread_mutex_lock(&mutex);             // 加锁
        while(_task.size() == 0)                // 任务队列为空
        {
            pthread_cond_signal(&cond);         // 唤醒一个生产者
            pthread_cond_wait(&cond, &mutex);   // 自己再等待生产者唤醒
        }
        Task task = _task.front();              // 获得任务
        _task.pop();                            // 删除任务
        pthread_mutex_unlock(&mutex);           // 解锁
        task(nullptr);                          // 执行任务
    }
    size_t _num;              // 最大任务数
private:
    std::queue<Task> _task;   // 任务队列
};

//-----------------------------------------------------------------------------------------

class c_thread // 消费者线程
{
private:
    bool CreatConsumerThread()
    {
        for (size_t i = 0; i < _num; i++)
        {
            // 创建线程
            pthread_t id;
            int n = pthread_create(&id, nullptr, _task, nullptr);
            if (n != 0) // 创建失败
            {
                lg(FATAL, "consumer thread create fail...");
                return false;
            }
            _ConsumerThread_v.push_back(id);
            lg(DEBUG, "a consumer thread create...all: %d", _ConsumerThread_v.size());
        }
        return true;
    }

     void WaitThread()
    {
        // 等待线程终止后销毁
        for (auto e : _ConsumerThread_v)
        {
            void *ret;
            pthread_join(e, &ret);
            int retu = (size_t)ret;
            lg(INFO, "c_thread's id is: %zu,return value is: %zu", e, retu);
        }
    }

public:
    c_thread(Task task, size_t num = C_NUM) :
    _num(num),
    _task(task)
    {
        // 创建消费者线程 && 执行方法
        CreatConsumerThread();
    }

    ~c_thread()
    {
        //_c_cond = PTHREAD_COND_INITIALIZER;
        WaitThread();
    }

private:
    size_t _num;                              // 消费者线程数量
    std::vector<pthread_t> _ConsumerThread_v; // 消费者线程的id
    Task _task;                               // 消费者线程执行的方法
};

//-----------------------------------------------------------------------------------------

class threadpool//线程池
{
public:
    threadpool(Task p_task,Task c_task,size_t p_num = P_NUM,size_t c_num = C_NUM):
    _p_thread(p_task,p_num),
    _c_thread(c_task,c_num),
    _p_task(p_task),
    _c_task(c_task)
    {
    }
    ~threadpool()
    {
        mutex = PTHREAD_MUTEX_INITIALIZER;
        cond = PTHREAD_COND_INITIALIZER;
    }
private:
    class p_thread _p_thread; // 生产者
    class c_thread _c_thread; // 消费者
    Task _p_task;             // 生产者任务
    Task _c_task;             // 消费者任务
};

